package com.thoughtworks.recruit.test.jgraph.graph;

import com.thoughtworks.recruit.test.jgraph.interfaces.DiGraph;
import com.thoughtworks.recruit.test.jgraph.interfaces.EdgeFactory;
import com.thoughtworks.recruit.test.jgraph.graph.builder.*;

/**
 * A directed graph. A default directed graph is a non-simple directed graph in which multiple edges
 * between any two vertices are <i>not</i> permitted, but loops are.
 *
 * 
 * @param <V> the graph vertex type
 * @param <E> the graph edge type
 * 
 */
public class DefaultDiGraph<V, E>
    extends AbstractBaseGraph<V, E>
    implements DiGraph<V, E>
{
    private static final long serialVersionUID = 1L;

    /**
     * Creates a new directed graph.
     *
     * @param edgeClass class on which to base factory for edges
     */
    public DefaultDiGraph(Class<? extends E> edgeClass)
    {
        this(new BasedEdgeFactory<>(edgeClass));
    }

    /**
     * Creates a new directed graph with the specified edge factory.
     *
     * @param ef the edge factory of the new graph.
     */
    public DefaultDiGraph(EdgeFactory<V, E> ef)
    {
        super(ef, false, true);
    }

    /**
     * Create a builder for this kind of graph.
     * 
     * @param edgeClass class on which to base factory for edges
     * @param <V> the graph vertex type
     * @param <E> the graph edge type
     * @return a builder for this kind of graph
     */
    public static <V,
        E> DiGraphBuilderBase<V, E, ? extends DefaultDiGraph<V, E>, ?> builder(
            Class<? extends E> edgeClass)
    {
        return new DiGraphBuilder<>(new DefaultDiGraph<>(edgeClass));
    }

    /**
     * Create a builder for this kind of graph.
     * 
     * @param ef the edge factory of the new graph
     * @param <V> the graph vertex type
     * @param <E> the graph edge type
     * @return a builder for this kind of graph
     */
    public static <V,
        E> DiGraphBuilderBase<V, E, ? extends DefaultDiGraph<V, E>, ?> builder(
            EdgeFactory<V, E> ef)
    {
        return new DiGraphBuilder<>(new DefaultDiGraph<>(ef));
    }
}
